package com.gxa.hualianeshop.jmslistener;

import com.gxa.hualianeshop.common.base.RedisKeys;
import com.gxa.hualianeshop.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import java.io.Serializable;

/**
 * 从队列中接收到订单消息后，
 * 先检查该 Token 是否存在于 Redis 中。
 * 如果 Token 存在，说明该订单是新订单，可以继续处理。
 * 处理订单时, 写入数据库,删除订单缓存
 * 消费者处理完订单后，将 Token 从 Redis 中删除，以释放该 Token，使其可以被再次使用
 *
 * 如果 Token 不存在，说明该订单已经被处理过，可以直接丢弃；
 * 要保证 判断->删除 是原子性, 是通过redis的lua脚本(编程)
 * RedisScript redis的lua脚本 , 可以存储为read-del.script
 *
 */
@Component
public class OrderIdListener {

    @Autowired
    private OrderService orderService;

    @Bean
    public SimpleJmsListenerContainerFactory firstFactory(ConnectionFactory connectionFactory) {
        SimpleJmsListenerContainerFactory factory=new SimpleJmsListenerContainerFactory();
        //关闭事务: 开启手动事务
        factory.setSessionTransacted(false);
        // 开启手动签收
        factory.setSessionAcknowledgeMode(4);
        factory.setConnectionFactory(connectionFactory);
        return factory;
    }

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @JmsListener(destination = "orderId",containerFactory = "firstFactory")
    public void saveOrder(Message message) throws JMSException {
        Serializable orderId = ((ObjectMessage) message).getObject();

        String key =  RedisKeys.SECURITY_TOKEN + orderId;

        String script = "local key = KEYS[1]\n" +
                "if redis.call('EXISTS', key) == 1 then\n" +
                "    redis.call('DEL', key)\n" +
                "    return 1\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        RedisCallback<Boolean> callback = connection -> {
            return connection.eval(script.getBytes(), ReturnType.BOOLEAN, 1, key.getBytes());
        };
        Boolean deleteResult = redisTemplate.execute(callback);

        if(deleteResult!=null && deleteResult){
            // 数据库操作
            orderService.concurrentCreate((Long)orderId);
            // 修改商品的sku的数量(扣库存)

        }

        /*Serializable orderId = ((ObjectMessage) message).getObject();

        Object securityToken = redisTemplate.opsForValue().get(RedisKeys.SECURITY_TOKEN + orderId);

        if(!StringUtils.isEmpty(securityToken)){
            // 数据库操作
            orderService.concurrentCreate((Long)orderId);
            // 删除token的缓存
            redisTemplate.delete(RedisKeys.SECURITY_TOKEN + orderId);

            // 删除订单中商品信息/价格/小计 临时缓存

        }*/
        message.acknowledge();

    }
}
